package cn.elead.chaos.framework.util;

import java.io.IOException;
import java.util.Objects;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.util.StreamUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import cn.elead.chaos.core.constant.APICons;
import cn.elead.chaos.core.converter.Convert;
import cn.elead.chaos.core.enums.HTTPMethod;
import cn.elead.chaos.core.util.StringUtils;
import cn.elead.chaos.core.util.TypeUtils;

import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * Request 请求工具类
 *
 * @author luopeng
 */
@Slf4j
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public abstract class RequestUtils {

	/**
	 * 判断请求方式GET
	 *
	 * @param request
	 * @return
	 */
	public static boolean isGet(HttpServletRequest request) {
		return HTTPMethod.GET.toString().equalsIgnoreCase(request.getMethod());
	}

	/**
	 * 判断请求方式POST
	 *
	 * @param request
	 * @return
	 */
	public static boolean isPost(HttpServletRequest request) {
		return HTTPMethod.POST.toString().equalsIgnoreCase(request.getMethod());
	}

	/**
	 * 判断请求方式PUT
	 *
	 * @param request
	 * @return
	 */
	public static boolean isPut(HttpServletRequest request) {
		return HTTPMethod.PUT.toString().equalsIgnoreCase(request.getMethod());
	}

	/**
	 * 判断请求方式DELETE
	 *
	 * @param request
	 * @return
	 */
	public static boolean isDelete(HttpServletRequest request) {
		return HTTPMethod.DELETE.toString().equalsIgnoreCase(request.getMethod());
	}

	/**
	 * 判断请求方式PATCH
	 *
	 * @param request
	 * @return
	 */
	public static boolean isPatch(HttpServletRequest request) {
		return HTTPMethod.PATCH.toString().equalsIgnoreCase(request.getMethod());
	}

	/**
	 * 判断请求方式TRACE
	 *
	 * @param request
	 * @return
	 */
	public static boolean isTrace(HttpServletRequest request) {
		return HTTPMethod.TRACE.toString().equalsIgnoreCase(request.getMethod());
	}

	/**
	 * 判断请求方式HEAD
	 *
	 * @param request
	 * @return
	 */
	public static boolean isHead(HttpServletRequest request) {
		return HTTPMethod.HEAD.toString().equalsIgnoreCase(request.getMethod());
	}

	/**
	 * 判断请求方式OPTIONS
	 *
	 * @param request
	 * @return
	 */
	public static boolean isOptions(HttpServletRequest request) {
		return HTTPMethod.OPTIONS.toString().equalsIgnoreCase(request.getMethod());
	}

	/**
	 * 获取请求
	 *
	 * @param request
	 * @return
	 */
	public static String getRequestBody(HttpServletRequest request) {
		String requestBody = null;
		/*
		 * if (isContainBody(request)) { try { ServletInputStream inputStream = null; if (request instanceof ShiroHttpServletRequest) { ShiroHttpServletRequest shiroRequest = (ShiroHttpServletRequest)
		 * request; inputStream = shiroRequest.getRequest().getInputStream(); } else { inputStream = request.getInputStream(); } if (Objects.nonNull(inputStream)) { StringWriter writer = new
		 * StringWriter(); IOUtils.copy(inputStream, writer, StandardCharsets.UTF_8.name()); requestBody = writer.toString(); } } catch (IOException ignored) { } }
		 */
		return requestBody;
	}

	/**
	 * 获取请求
	 *
	 * @param request
	 * @return
	 */
	public static byte[] getByteBody(HttpServletRequest request) {
		byte[] body = new byte[0];
		try {
			body = StreamUtils.copyToByteArray(request.getInputStream());
		} catch (IOException e) {
			log.error("Error: Get RequestBody byte[] fail," + e);
		}
		return body;
	}

	/**
	 * 是否包含请求体
	 *
	 * @param request
	 * @return
	 */
	public static boolean isContainBody(HttpServletRequest request) {
		return isPost(request) || isPut(request) || isPatch(request);
	}

	/**
	 * 是否是Ajax异步请求
	 *
	 * @param request
	 */
	public static boolean isAjaxRequest(HttpServletRequest request) {
		Boolean isRestResult = TypeUtils.castToBoolean(getRequest().getAttribute(APICons.API_REST_RESULT));
		if (Objects.nonNull(isRestResult)) {
			return isRestResult;
		}
		String accept = request.getHeader("accept");
		if (accept != null && accept.contains("application/json")) {
			return true;
		}

		String xRequestedWith = request.getHeader("X-Requested-With");
		if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest")) {
			return true;
		}

		String uri = request.getRequestURI();
		if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml")) {
			return true;
		}

		String ajax = request.getParameter("__ajax");
		return StringUtils.inStringIgnoreCase(ajax, "json", "xml");
	}

	/**
	 * 获取http请求的Domain
	 *
	 * @param request
	 * @return
	 */
	public static String getDomain(HttpServletRequest request) {
		StringBuffer url = request.getRequestURL();
		String contextPath = request.getServletContext().getContextPath();
		return url.delete(url.length() - request.getRequestURI().length(), url.length()).append(contextPath).toString();
	}

	/**
	 * 获取完整的请求路径，包括：域名，端口，上下文访问路径
	 * 
	 * @return 服务地址
	 */
	public static String getUrl() {
		HttpServletRequest request = RequestUtils.getRequest();
		return getDomain(request);
	}

	/**
	 * 获取String参数
	 */
	public static String getParameter(String name) {
		return getRequest().getParameter(name);
	}

	/**
	 * 获取String参数
	 */
	public static String getParameter(String name, String defaultValue) {
		return Convert.toStr(getRequest().getParameter(name), defaultValue);
	}

	/**
	 * 获取Integer参数
	 */
	public static Integer getParameterToInt(String name) {
		return Convert.toInt(getRequest().getParameter(name));
	}

	/**
	 * 获取Integer参数
	 */
	public static Integer getParameterToInt(String name, Integer defaultValue) {
		return Convert.toInt(getRequest().getParameter(name), defaultValue);
	}

	/**
	 * 获取request
	 */
	public static HttpServletRequest getRequest() {
		return getRequestAttributes().getRequest();
	}

	/**
	 * 获取response
	 */
	public static HttpServletResponse getResponse() {
		return getRequestAttributes().getResponse();
	}

	/**
	 * 获取session
	 */
	public static HttpSession getSession() {
		return getRequest().getSession();
	}

	public static ServletRequestAttributes getRequestAttributes() {
		RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
		return (ServletRequestAttributes) attributes;
	}

}
